
/* inferno's Lua API

A Lua supplement built in C++
ilapi.googlecode.com

See copyright and license in iLapi.h
***

Declaration of ilapi namespace

iLapi.cpp */


extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}

#include "iLapi.h"


/* ilapi::L
namespace'd "global" lua_State used by ilapi
*/
lua_State *ilapi::L;

/* ilapi::minstack
the minimum stack size
*/
int ilapi::minstack = 10;
/* ilapi::registeredvar, ilapi::registeredvalue
arrays of registered variables (and the appropriate values)
that are not to be adjusted from Lua
*/
char *ilapi::registeredvar[1000];
char *ilapi::registeredvalue[1000];


/* ilapi::init

returns false on error, else true (while pushing the error on top of the stack)
if you don't want to use it, simple set ilapi::L to a custom state
*/
bool ilapi::init (bool _lib, int _minstack) {
// create a new Lua state for ilapi::L
if ((ilapi::L = luaL_newstate()) == NULL) {
    lua_pushstring (ilapi::L, "iLapi failed to initialize state\n");
    return false;
}

// activate all auxilary libraries for Lua
luaL_openlibs (ilapi::L);

if (_minstack)
ilapi::minstack = _minstack;

if (_lib)
ilapi::lib::load();

return true;
};

/* ilapi::run
checks the stack size and performs general maintenance on the lua_State
*/
void ilapi::run() {
if (!lua_checkstack (ilapi::L, ilapi::minstack))
lua_pop (ilapi::L, ilapi::minstack);

return;
}

/* ilapi::close
frees all Lua and iLapi memory
*/
void ilapi::close() {
lua_close (ilapi::L);
return;
};

/* ilapi::registercfunc
registers an existing C++ function of type "static int (lua_State*)"
to the given Lua function name.  like the default Lua register method,
a user can easily override this function within Lua itself
*/
void ilapi::registercfunc (const char *lfunc, lua_CFunction cfunc) {
lua_pushcclosure (ilapi::L, cfunc, 0);
lua_setfield (L, LUA_GLOBALSINDEX, lfunc);
return;
};

/* ilapi::exec
execute function "name"
*/
void ilapi::exec (const char *func) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, func);
if (lua_isfunction(L,-1))
lua_pcall (ilapi::L, 0, 0, 0);
return;
};

/* ilapi::registervar
an advanced function that takes the value on top of the stack and sets
the Lua global name to it.  this variable is then added
to
void registervar (const char *name) {

};

void checkregisteredvar (const char *name) {

};
*/
/* ilapi::parse namespace
*/

int ilapi::parse::file (const char *filename) {
return (luaL_loadfile (ilapi::L, filename) || lua_pcall (ilapi::L, 0, LUA_MULTRET, 0));
};

int ilapi::parse::string (const char *str) {
return (luaL_loadstring (ilapi::L, str) || lua_pcall (ilapi::L, 0, LUA_MULTRET, 0));
};

void ilapi::parse::varstring (const char *str) {
int i = 0, t = 0;
bool table = false;
int end = strlen(str);
char *buffer = new char[256];
while (i <= end) {
if (str[i] == '.' || i == end) {
    if (i == end) {
    buffer[t] = str[i];
    t++;
    buffer[t] = '\0';
    }
    if (!table)
        lua_getglobal (ilapi::L, buffer);
        else {
        lua_pushstring (ilapi::L, buffer);
        lua_gettable (ilapi::L, -2);
        }
    delete [] buffer;
    buffer = new char[1024];
    t = 0;
    table = true;
} else {
    buffer[t] = str[i];
    t++;
    buffer[t] = '\0';
    }
i++;
}
return;
};


/* ilapi::table namespace
a set of functions for obtaining data from global tables
*/

/* ilapi::ltable::pushnumindex
pushes the value at the given index onto the stack
*/
void ilapi::table::pushnumindex (const char *table, int i) {
ilapi::get::table (table);
lua_pushnumber (ilapi::L, i);
lua_gettable (ilapi::L, -2);
return;
};

/* ilapi::table::pushcharindex
pushes the value at the index of the given name onto the stack
*/
void ilapi::table::pushcharindex (const char *table, const char *c) {
ilapi::get::table (table);
lua_pushstring (ilapi::L, c);
lua_gettable (ilapi::L, -2);
return;
};



/* ilapi::get namespace
a set of functions that allow easy access to Lua globals
from C++
*/

const char *ilapi::get::string (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (!lua_isstring (ilapi::L, -1))
return "NaStr";
else return lua_tostring (ilapi::L, -1);
};

lua_Number ilapi::get::number (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (!lua_isnumber (ilapi::L, -1))
return 0;
else return lua_tonumber (ilapi::L, -1);
};

bool ilapi::get::boolean (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (!lua_isboolean (ilapi::L, -1))
return false;
else return lua_toboolean (ilapi::L, -1);
};

/* ilapi::get::table
a different "get" function, it merely pushes the table onto the stack
*/
void ilapi::get::table (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (!lua_istable (ilapi::L, -1)) {
lua_createtable (ilapi::L, 0, 0);
lua_setfield (ilapi::L, LUA_GLOBALSINDEX, name);
return;
} else return;
};

/* ilapi::set namespace
a set of functions that allow easy declaration of Lua globals
from C++
*/

// set variable name to value str
void ilapi::set::string (const char *name, const char *str) {
lua_pushstring (ilapi::L, str);
lua_setfield (ilapi::L, LUA_GLOBALSINDEX, name);
return;
};

void ilapi::set::number (const char *name, lua_Number val) {
lua_pushnumber (ilapi::L, val);
lua_setfield (ilapi::L, LUA_GLOBALSINDEX, name);
return;
};

void ilapi::set::boolean (const char *name, bool val) {
lua_pushboolean (ilapi::L, val);
lua_setfield (ilapi::L, LUA_GLOBALSINDEX, name);
return;
};

void ilapi::set::nil (const char *name) {
lua_pushnil (ilapi::L);
lua_setfield (ilapi::L, LUA_GLOBALSINDEX, name);
return;
};

/* ilapi::is namespace
a set of functions that determine if a Lua variable is of a given type
you do not need to call these when accessing a variable; the ilapi::get
functions do this automatically
*/

bool ilapi::is::string (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (lua_isstring (ilapi::L, -1))
return true;
else return false;
};

bool ilapi::is::number (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (lua_isnumber (ilapi::L, -1))
return true;
else return false;
};

bool ilapi::is::boolean (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (lua_isboolean (ilapi::L, -1))
return true;
else return false;
};

bool ilapi::is::nil (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (lua_isnil (ilapi::L, -1))
return true;
else return false;
};

bool ilapi::is::none (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (lua_isnone (ilapi::L, -1))
return true;
else return false;
};

bool ilapi::is::noneornil (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (lua_isnoneornil (ilapi::L, -1))
return true;
else return false;
};

bool ilapi::is::table (const char *name) {
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, name);
if (lua_istable (ilapi::L, -1))
return true;
else return false;
};

/* ilapi::push namespace
a set of functions for pushing values onto the stack
*/

void ilapi::push::string (const char *val) {
lua_pushstring (ilapi::L, (char*)val);
return;
};

void ilapi::push::number (lua_Number val) {
lua_pushnumber (ilapi::L, val);
return;
};

void ilapi::push::boolean (bool val) {
lua_pushboolean (ilapi::L, val);
return;
}

void ilapi::push::nil() {
lua_pushnil (ilapi::L);
return;
};

/* ilapi::lib namespace
a set of Lua functions, prefixed with ilapi_, for general use,
as well as a number of non-prefixed functions
*/

void ilapi::lib::load() {
ilapi::registercfunc ("ilapi_help", ilapi::lib::help);
ilapi::registercfunc ("ilapi_memory", ilapi::lib::memory);
ilapi::registercfunc ("ilapi_print", ilapi::lib::print);
return;
};

int ilapi::lib::help (lua_State *L) {
std::cout << std::endl <<
"ilapi_memory()     Returns the current memory, in KB, that iLapi is using";
std::cout << std::endl <<
"ilapi_print()      Prints all parameters to the std::cout stream, followed by a newline";
std::cout << std::endl;
return 0;
};

int ilapi::lib::memory (lua_State *L) {
lua_pushinteger (L, lua_gc (L, LUA_GCCOUNT, 0));
return 1;
};

int ilapi::lib::print (lua_State *L) {
for (int tmp = 1; tmp <= lua_gettop(L); ++tmp) {
if (lua_isstring (L, tmp))
std::cout << lua_tostring (L, tmp);
else if (lua_isnumber (L, tmp))
std::cout << lua_tointeger (L, tmp);
}
std::cout << std::endl;
return 0;
};



/* ilapi::ltable class
a generic class for Lua tables
*/

/* ilapi::ltable::pushnumindex
pushes the value at the given index onto the stack
*/
void ilapi::ltable::pushnumindex (int i) {
ilapi::get::table (name);
lua_pushnumber (ilapi::L, i);
lua_gettable (ilapi::L, -2);
};

/* ilapi::ltable::pushcharindex
pushes the value at the index of the given name onto the stack
*/
void ilapi::ltable::pushcharindex (const char *c) {
ilapi::get::table (name);
lua_pushstring (ilapi::L, c);
lua_gettable (ilapi::L, -2);
};

/* ilapi::ltable constructors
*/
ilapi::ltable::ltable () {
name = NULL;
};

ilapi::ltable::ltable (const char *_name) {
name = _name;
};

ilapi::ltable::ltable (const char *_name, int num, ...) {
name = _name;
va_list argptr;
num *= 2;
va_start (argptr, num);
lua_getfield (ilapi::L, LUA_GLOBALSINDEX, _name);
if (!lua_istable (ilapi::L, -1))
lua_createtable (ilapi::L, 0, 0);
for (; num > 0; num--) {
lua_pushstring (ilapi::L, va_arg (argptr, char*));
num--;
lua_pushstring (ilapi::L, va_arg (argptr, char*));
lua_settable (ilapi::L, -3);
}
lua_setfield (ilapi::L, LUA_GLOBALSINDEX, _name);
va_end( argptr );
};

ilapi::ltable::~ltable() {
name = NULL;
};


/* ilapi::lvar class
a generic class for Lua variables that supports
variable hierarchies (classes)
*/

void ilapi::lvar::pushvalue() {
lua_pushstring (ilapi::L, value);
return;
}

ilapi::lvar::lvar() {
name = NULL;
value = NULL;
parent = NULL;
}

ilapi::lvar::lvar (const char *_name) {
name = _name;
value = NULL;
parent = NULL;
};

ilapi::lvar::lvar (const char *_name, char *_value) {
name = _name;
value = _value;
parent = NULL;
};

ilapi::lvar::lvar (const char *_name, ltable *_parent) {
name = _name;
value = NULL;
parent = _parent;
};

ilapi::lvar::lvar (const char *_name, char *_value, ltable *_parent) {
name = _name;
value = _value;
parent = _parent;
};

ilapi::lvar::~lvar() {
name = NULL;
value = NULL;
parent = NULL;
};

